package cn.bincker.mybatis.encrypt.exception;

import cn.bincker.mybatis.encrypt.reflection.ReflectionUtils;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;

import java.util.stream.Collectors;

@Getter
public class PropertyEncryptException extends MybatisEncryptException{
    private final Class<?> entityClass;
    private final Object target;
    private final String property;

    public PropertyEncryptException(Class<?> entityClass, Object target, String property) {
        super(
                "decrypt fail: class=" + entityClass.getName() +
                        "\tproperty=" + property +
                        "\tid=" + ReflectionUtils.getEntityIds(target).stream().map(String::valueOf).collect(Collectors.joining(","))
        );
        this.entityClass = entityClass;
        this.target = target;
        this.property = property;
    }

    public PropertyEncryptException(Class<?> entityClass, Object target, String property, Throwable cause) {
        super(
                "decrypt fail: class=" + entityClass.getName() +
                        "\tproperty=" + property +
                        "\tid=" + ReflectionUtils.getEntityIds(target).stream().map(String::valueOf).collect(Collectors.joining(",")),
                cause
        );
        this.entityClass = entityClass;
        this.target = target;
        this.property = property;
    }

    public String getIdsString(){
        return ReflectionUtils.getEntityIds(target).stream().map(String::valueOf).collect(Collectors.joining(","));
    }

    public String getTableName(){
        var tableName = entityClass.getAnnotation(TableName.class);
        if(tableName == null) return "";
        return (tableName.schema().isBlank() ? "" : tableName.schema() + ".") + tableName.value();
    }

    public String getColumn(){
        try {
            var field = entityClass.getDeclaredField(property);
            var tableField = field.getAnnotation(TableField.class);
            if (tableField != null) return tableField.value();
            var columnName = new StringBuilder();
            for (char c : property.toCharArray()) {
                if (Character.isUpperCase(c)){
                    columnName.append("_");
                }
                columnName.append(Character.toLowerCase(c));
            }
            return columnName.toString();
        } catch (NoSuchFieldException ignore) {
            return "";
        }
    }
}
